#include "ET++.ph"
#ifdef __GNUG__
#pragma implementation
#endif

#include "Converter.h"

#include "Class.h"
#include "String.h"
#include "Data.h"
#include "OrdColl.h"
#include "ClassManager.h"
#include "ET_stdio.h"

//---- Converter ---------------------------------------------------------------

ONEXIT(Converter)
{
	Converter::CleanUp();
}

NewMetaImpl(Converter,Object, (TP(filters)));

OrdCollection *Converter::filters;

Converter::Converter()
{
}

const char *Converter::AsString()
{
	return "Abstract Converter";
}

void Converter::CleanUp()
{
	if (filters) {
		filters->FreeAll();
		SafeDelete(filters);
	}
}

OrdCollection *Converter::CollectConverters()
{
	if (filters == 0) {
		Iter next(gClassManager->Iterator());
		Class *cla;

		filters= new OrdCollection;
		while (cla= (Class*)next())
			if (cla->isKindOf(Meta(Converter)) && cla != Meta(Converter))
				filters->Add(cla->Proto()->New());
	}
	return filters;
}

OrdCollection *Converter::CollectOutputConverters(Object *op)
{
	OrdCollection *converters= new OrdCollection;
	Iter next(CollectConverters());
	register Converter *filter;

	while (filter= (Converter*) next()) {
		if (filter->CanConvertTo(op)) {
			if (converters->FindPtr(filter) == 0) {
				converters->Add(filter);
			}
		}
	}
	if (converters->Size() < 1)
		SafeDelete(converters);
	return converters;
}

Converter *Converter::FindConverter(Data *data, Class *want, OrdCollection *l)
{
	Iter next(CollectConverters());
	register Converter *filter;

	while (filter= (Converter*) next()) {
		if (filter->CanConvert(data, want)) {
			if (gDebug)
				fprintf(stderr, "Converter::FindConverter: %s\n", filter->AsString());
			if (l == 0)
				return filter;
			if (l->FindPtr(filter) == 0)
				l->AddFirst(filter);
		}
	}
	if (l && l->Size() > 0)
		return (Converter*)l->At(0);
	if (gDebug)
		fprintf(stderr, "Converter::FindConverter: no filter found\n");
	return 0;
}

bool Converter::CanConvert(Data*, Class*)
{
	return FALSE;
}

Object *Converter::Convert(Data*, Class*)
{
	return 0;
}

bool Converter::CanConvertTo(Object*)
{
	return FALSE;
}

bool Converter::ConvertTo(Data*, Object*)
{
	return FALSE;
}

